﻿using System;
using System.Collections.Generic;
using System.Linq;
using MarriageFertility.banner;
using MarriageFertility.Helpers;
using MarriageFertility.Texts;
using TaleWorlds.CampaignSystem;
using TaleWorlds.CampaignSystem.Actions;
using TaleWorlds.CampaignSystem.Party;
using TaleWorlds.CampaignSystem.Party.PartyComponents;
using TaleWorlds.CampaignSystem.Settlements;
using TaleWorlds.Core;
using TaleWorlds.Library;
using TaleWorlds.Localization;
using SandBox.View.Map;
using TaleWorlds.CampaignSystem.Conversation;

namespace MarriageFertility.Dialogs;

public static class ClanDialog
{
    private static Clan _clan;

    public static void AddDialogs(CampaignGameStarter campaignGameStarter)
    {
        AddClanDialogs(campaignGameStarter);
        AddJoinOtherClanDialog(campaignGameStarter);
    }

    private static void AddClanDialogs(CampaignGameStarter campaignGameStarter)
    {
        campaignGameStarter.AddPlayerLine("create_new_clan_command", "hero_main_options", "request_to_create_clan",
            ClanText.CreateClan, CanCreateClan, null);

        campaignGameStarter.AddDialogLine("npc_response_to_create_clan", "request_to_create_clan",
            "npc_ask_for_further_instructions",
            ClanText.ResponseCreateClan, null, CreateNewClan);
        
        campaignGameStarter.AddPlayerLine("player_asks_for_joining_clan", "npc_ask_for_further_instructions",
            "request_to_join_npc_clan",
            ClanText.AskJoinClan, HasMembers, ShowJoinMembers);

        campaignGameStarter.AddDialogLine("npc_response_to_join_clan", "request_to_join_npc_clan",
            "npc_ask_for_further_instructions",
            ClanText.ResponseJoinClan, null, null);

        campaignGameStarter.AddPlayerLine("player_asks_to_join_kingdom", "npc_ask_for_further_instructions",
            "request_to_join_kingdom",
            ClanText.AskJoinKingdom, HasOneKingdom, null);

        campaignGameStarter.AddDialogLine("lord_response_join_one_kingdom", "request_to_join_kingdom", "hero_leave",
            ClanText.FinalGoodbye, JoinOneKingdom, null);

        campaignGameStarter.AddPlayerLine("create_new_kingdom_command", "npc_ask_for_further_instructions",
            "request_to_create_kingdom",
            ClanText.CreateKingdom, CanCreateKingdom, null);

        campaignGameStarter.AddDialogLine("npc_response_to_create_kingdom", "request_to_create_kingdom",
            "npc_ask_for_kingdom_name",
            ClanText.ResponseCreateKingdom, null, null);

        campaignGameStarter.AddDialogLine("final_response_create_kingdom", "npc_ask_for_kingdom_name", "hero_leave",
            ClanText.FinalGoodbye, CreateNewKingdom, null);
    }
    
    
    private static void AddJoinOtherClanDialog(CampaignGameStarter campaignGameStarter)
    {
        // 玩家请求将家族成员加入其他家族
        campaignGameStarter.AddPlayerLine("player_asks_to_join_other_clan", "hero_main_options",
            "request_to_join_other_clan", ClanText.AskJoinOtherClan, HasMembersInSameKingdom, ShowJoinOtherClanMembers);

        // NPC回应
        campaignGameStarter.AddDialogLine("npc_response_to_join_other_clan", "request_to_join_other_clan",
            "hero_leave", ClanText.ResponseJoinOtherClan, null, null);
    }


    private static bool CanCreateClan()
    {
        Hero hero = Hero.OneToOneConversationHero;
        return hero != null && hero.Clan == Clan.PlayerClan && hero.IsAlive && hero.Age >= 18;
    }

    private static bool CanCreateKingdom()
    {
        Hero hero = Hero.OneToOneConversationHero;
        return hero != null && (hero.Clan == _clan || hero.CompanionOf== _clan ) && hero.IsAlive && hero.Age >= 18 &&
               Clan.PlayerClan.Settlements.Any(s => s.IsTown);
    }


    private static bool HasMembers() =>
        Clan.PlayerClan.Heroes.Any(h => h.IsAlive && h != Hero.MainHero && !h.IsPartyLeader);

    private static void ShowJoinMembers()
    {
        Hero hero = Hero.OneToOneConversationHero;
        if (hero == null) return;

        MBInformationManager.ShowMultiSelectionInquiry(
            new MultiSelectionInquiryData(ClanText.MemberSelection, ClanText.SelectMembersToJoin,
                GetInquiryHeroes(), true, 1, 30,
                CommonText.Confirm, CommonText.Cancel, JoinClan, null), true);
    }


    private static void CreateNewClan()
    {
        Hero hero = Hero.OneToOneConversationHero;
        if (hero == null) return;
        
        InformationManager.ShowInquiry(new InquiryData(
            new TextObject("{=MF_create_clan_title}Create New Clan").ToString(), // Title
            new TextObject("{=MF_create_clan_confirm}Are you sure you want to create a new clan?").ToString(), // Confirmation message
            true, // Show affirm button
            true, // Show cancel button
            new TextObject("{=MF_confirm}Confirm").ToString(), // Affirm button text
            new TextObject("{=MF_cancel}Cancel").ToString(), // Cancel button text
            () =>
            {
                Helper.ChangeCompanionOccupation(hero);
                TextObject clanName = new TextObject("{=MF_clan_name}Clan {hero}");
                Clan clan = Clan.CreateClan(hero.StringId + "clan");
                clanName.SetTextVariable("hero", hero.Name);
                int iconMeshId = Hero.MainHero.MapFaction.Culture.PossibleClanBannerIconsIDs.GetRandomElement();
                clan.InitializeClan(
                    clanName,
                    clanName,
                    hero.Culture,
                    Banner.CreateOneColoredBannerWithOneIcon(
                        Clan.PlayerClan.Banner.GetFirstIconColor(),
                        Clan.PlayerClan.Banner.GetPrimaryColor(),
                        iconMeshId),
                    MobileParty.MainParty.Position2D);
                AssignClanAndLeader(hero, clan);
                OpenBannerEditorScreen(clan);
            },
            () =>
            {
                InformationManager.DisplayMessage(new InformationMessage(
                    new TextObject("{=MF_create_clan_cancelled}Clan creation has been cancelled.").ToString()));
                Campaign.Current.ConversationManager.EndConversation();
            }
        ));
    }
    
    private static void OpenBannerEditorScreen(Clan clan)
    {
        if (!Campaign.Current.IsBannerEditorEnabled) return;
        ReflectUtils.SetNotPublicVar(MapScreen.Instance, "_partyIconNeedsRefreshing", true);
        Game.Current.GameStateManager.PushState(Game.Current.GameStateManager.CreateState<MfBannerEditorState>(clan));
    }

    private static void AssignClanAndLeader(Hero hero, Clan clan)
    {
        hero.Clan?.Heroes?.Remove(hero);
        hero.CompanionOf?.Heroes.Remove(hero);
        hero.CompanionOf = null;
        hero.Clan = clan;
        clan.SetLeader(hero);
        _clan = clan;
        clan.AddRenown(MBRandom.RandomInt(5000, 10000));
        clan.Leader.ChangeHeroGold(MBRandom.RandomInt(30000, 50000));
        InformationManager.ShowTextInquiry(new TextInquiryData(ClanText.EnterClanName,
            string.Empty, true, false, GameTexts.FindText("str_done").ToString(), null, ChangeClanName, null));
        ClanHelper.RemoveHeroFromParty(hero);
    }

    private static void ChangeClanName(string name)
    {
        _clan.ChangeClanName(new TextObject(name), null);
    }

    private static List<InquiryElement> GetInquiryHeroes() =>
        Hero.MainHero.Clan.Heroes
            .Where(h => h.IsAlive && h != Hero.MainHero && !h.IsPartyLeader)
            .Select(clanMember => new InquiryElement(clanMember, clanMember.Name.ToString(),
                new ImageIdentifier(CharacterCode.CreateFrom(clanMember.CharacterObject))))
            .ToList();

    private static List<InquiryElement> GetInquiryKingdoms() =>
        Kingdom.All
            .Where(k => !k.IsEliminated && k.Settlements.Any())
            .Select(kingdom =>
                new InquiryElement(kingdom, kingdom.Name.ToString(), new ImageIdentifier(kingdom.Banner)))
            .ToList();

    private static void JoinClan(List<InquiryElement> elements)
    {
        foreach (Hero hero in elements.Select(element => element.Identifier as Hero))
        {
            Helper.ChangeCompanionOccupation(hero);
            hero.CompanionOf = null;
            hero.Clan = _clan;
            ClanHelper.RemoveHeroFromParty(hero);
        }
    }
    
    private static void ShowJoinOtherClanMembers()
    {
        Hero hero = Hero.OneToOneConversationHero;
        if (hero == null) return;

        // 获取同一王国内的其他家族
        var availableClans = Hero.MainHero.Clan.Kingdom.Clans.Where(c => c != hero.Clan).ToList();

        if (availableClans.Any())
        {
            // 显示选择家族的对话框
            MBInformationManager.ShowMultiSelectionInquiry(
                new MultiSelectionInquiryData(ClanText.ChooseClan, ClanText.SelectMembersToJoinOtherClan,
                    GetInquiryClans(availableClans), true, 1, 30,
                    CommonText.Confirm, CommonText.Cancel, HeroJoinOtherClan, null), true);
        }
        else
        {
            InformationManager.DisplayMessage(new InformationMessage("No available clans to join in the same kingdom.", Colors.Red));
        }
    }
    
    private static List<InquiryElement> GetInquiryClans(List<Clan> clans)
    {
        return clans.Select(clan => new InquiryElement(clan, clan.Name.ToString(),
            new ImageIdentifier(clan.Banner))).ToList();
    }

    private static void HeroJoinOtherClan(List<InquiryElement> elements)
    {
        Clan clan=elements.First()?.Identifier as Clan;
        Hero hero = Hero.OneToOneConversationHero;
        if (clan != null && hero != null)
        {  
            Helper.ChangeCompanionOccupation(hero);
            Hero.OneToOneConversationHero.CompanionOf = null;
            Hero.OneToOneConversationHero.Clan = clan; // 保持在同一个王国内，但加入新的家族
            if(!hero.IsPartyLeader)
            {
                ClanHelper.RemoveHeroFromParty(hero);
                SpawnParty(hero, clan.Kingdom.Settlements.GetRandomElement());
            }
        }
    }
    
    private static bool JoinOneKingdom()
    {
        Hero hero = Hero.OneToOneConversationHero;
        List<InquiryElement> kingdoms = GetInquiryKingdoms();
        if (hero == null || kingdoms.Count <= 0) return false;

        MBInformationManager.ShowMultiSelectionInquiry(
            new MultiSelectionInquiryData(
                ClanText.KingdomSelection, // 对话框标题
                ClanText.SelectKingdomToJoin, // 对话框描述
                kingdoms, // 获取可加入的国家列表
                true,
                1, 1,
                CommonText.Confirm, // 确认按钮文本
                CommonText.Cancel, // 取消按钮文本
                JoinKingdom, // 确认后的回调函数
                null // 取消后的回调函数
            ),
            true
        );
        return true;
    }
    
    private static bool HasMembersInSameKingdom()
    {
        Hero hero = Hero.OneToOneConversationHero;
        if (Clan.PlayerClan.Kingdom==null || hero == null || hero.Clan != Clan.PlayerClan || hero.IsFactionLeader) return false;
        if(Clan.PlayerClan.Kingdom.Clans.Count(c=>c!=Clan.PlayerClan)<=0) return false;
        return true;
    }


    private static bool HasOneKingdom() => Kingdom.All.Any(k => !k.IsEliminated);

    private static void JoinKingdom(List<InquiryElement> elements)
    {
        try
        {
            Kingdom kingdom = elements.Select(e => e.Identifier).OfType<Kingdom>().FirstOrDefault();
            if (kingdom == null) return;
            ChangeKingdomAction.ApplyByJoinToKingdom(_clan, kingdom);
            _clan.Heroes.ForEach(hero => SpawnParty(hero, kingdom.Settlements.GetRandomElement()));
        }
        catch (Exception ex)
        {
            Log.ErrorMessage(ex.StackTrace);
        }
    }

    private static bool CreateNewKingdom()
    {
        Hero hero = Hero.OneToOneConversationHero;
        if (hero == null || hero.Clan == null) return true;
        Clan clan = hero.Clan;

        List<InquiryElement> cultures = GetAvailableCultures();

        MBInformationManager.ShowMultiSelectionInquiry(new MultiSelectionInquiryData(
            ClanText.SelectCulture, // Dialog title
            ClanText.SelectCultureDescription, // Dialog description
            cultures, // List of available cultures
            true, 1, 1,
            CommonText.Confirm, // Confirm button text
            CommonText.Cancel, // Cancel button text
            selectedCulture =>
            {
                CultureObject culture = selectedCulture.FirstOrDefault()?.Identifier as CultureObject;
                if (culture == null) return;

                List<InquiryElement> playerSettlements = GetPlayerSettlements();

                MBInformationManager.ShowMultiSelectionInquiry(new MultiSelectionInquiryData(
                    ClanText.SelectSettlement, // Dialog title
                    ClanText.SelectSettlementDescription, // Dialog description
                    playerSettlements, // List of player-owned settlements
                    true, 1, 1,
                    CommonText.Confirm, // Confirm button text
                    CommonText.Cancel, // Cancel button text
                    selectedSettlement =>
                    {
                        Settlement settlement = selectedSettlement.FirstOrDefault()?.Identifier as Settlement;
                        if (settlement == null) return;

                        // Show an inquiry to enter the kingdom name
                        InformationManager.ShowTextInquiry(new TextInquiryData(
                            ClanText.EnterKingdomName, // Dialog title
                            string.Empty, true, false,
                            GameTexts.FindText("str_done").ToString(), null,
                            kingdomName =>
                            {
                                if (string.IsNullOrWhiteSpace(kingdomName)) return;
                                ChangeOwnerOfSettlementAction.ApplyByGift(settlement, hero);

                                // Show an inquiry to enter the encyclopedia text
                                InformationManager.ShowTextInquiry(new TextInquiryData(
                                    ClanText.EnterEncyclopediaText, // Dialog title for encyclopedia text
                                    string.Empty, true, false,
                                    GameTexts.FindText("str_done").ToString(), null,
                                    encyclopediaText =>
                                    {
                                        if (string.IsNullOrWhiteSpace(encyclopediaText)) return;
                                        // Create the new kingdom
                                        Kingdom kingdom = Kingdom.CreateKingdom(kingdomName);

                                        // Initialize the kingdom
                                        kingdom.InitializeKingdom(
                                            new TextObject(kingdomName), // name
                                            new TextObject(kingdomName), // informalName
                                            culture, // culture
                                            clan.Banner, // banner
                                            clan.Banner.GetFirstIconColor(), // kingdomColor1
                                            clan.Banner.GetPrimaryColor(), // kingdomColor2
                                            settlement, // initialHomeland
                                            new TextObject(encyclopediaText), // encyclopedia text
                                            new TextObject("{=MF_encyclopedia_title}Encyclopedia title placeholder."),
                                            new TextObject(
                                                "{=MF_encyclopedia_ruler_title}Encyclopedia ruler title placeholder.")
                                        );
                                        kingdom.RulingClan = clan;
                                        clan.Kingdom = kingdom;
                                        var k = hero.MapFaction;
                                        _clan.Heroes.ForEach(hero =>
                                            SpawnParty(hero, kingdom.Settlements.GetRandomElement()));
                                    },
                                    null));
                            },
                            null));
                    },
                    null));
            },
            null
        ), true);
        return true;
    }


    private static List<InquiryElement> GetAvailableCultures()
    {
        return Campaign.Current.ObjectManager.GetObjectTypeList<CultureObject>()
            .Select(culture => new InquiryElement(culture, culture.Name.ToString(), null))
            .ToList();
    }

    private static List<InquiryElement> GetPlayerSettlements()
    {
        return Clan.PlayerClan.Settlements.Where(s => s.IsTown)
            .Select(settlement => new InquiryElement(settlement, settlement.Name.ToString(),
                new ImageIdentifier(settlement.OwnerClan.Banner)))
            .ToList();
    }

    private static void SpawnParty(Hero hero, Settlement settlement)
    {
        if (hero.Age < 18) return;
        if (hero.PartyBelongedTo != null && hero.PartyBelongedTo != MobileParty.MainParty)
            hero.PartyBelongedTo.RemoveParty();

        MobileParty lordParty =
            LordPartyComponent.CreateLordParty(null, hero, MobileParty.MainParty.Position2D, 3f, settlement, hero);

        lordParty.MemberRoster.AddToCounts(Clan.PlayerClan.Culture.BasicTroop, MBRandom.RandomInt(20, 50));
        lordParty.MemberRoster.AddToCounts(Clan.PlayerClan.Culture.EliteBasicTroop, MBRandom.RandomInt(20, 50));
    }
}